#include "syscall.h"
#include "print.c"

/************************************************************
 
        Test 3 : use lock and condition syscall in right order 
                         (the order should be t1->t3->t2)

*************************************************************/
#define TRUE 1
#define FALSE 0


int lock;	/*lock to ensure that the share data is protected from race condition*/
int lockCV;	/*for broadcast test*/
int lockCV1;
int lockCV2;


int flag1 = FALSE;
int flag2 = FALSE;
int flag3 = FALSE;  /*make sure the broadcast test runs after the first test*/

int count = 0;
int countLock;

int cleanupLock;
int cleanupCV;
int cleanupThreads = 0;
int shareData = 0;

int mainLock;  /*make sure the running order*/
int mainLockCV;

void t1(){

        int printMsg[1];
/*
        Acquire(cleanupLock);
        cleanupThreads++;
        Release(cleanupLock);
*/
        
        Acquire(lock);

        printString("t1 is working in C.S.\n");
        printMsg[0] = shareData;
        printf("The shared data now is [%d]. (Should be 0)\n", printMsg);
        shareData++;

	flag1 = TRUE;
	Signal(lockCV1, lock);

        Release(lock);
        
        printString("t1 Complete.\n");
/*
        Acquire(cleanupLock);
        cleanupThreads--;
	Signal(cleanupCV, cleanupLock);
        Release(cleanupLock);
*/
	Exit(0);
}

void t2(){

        int printMsg[2];
/*
        Acquire(cleanupLock);
        cleanupThreads++;
        Release(cleanupLock);
*/

        Acquire(lock);

	if(flag2 == FALSE) {
		printMsg[0] = lockCV2;
		printMsg[1] = lock;
		printf("t2 is waiting on condition %d with lock %d\n", printMsg);
		Wait(lockCV2, lock);
	}        

		printString("t2 is signaled to run\n");
		printString("t2 is working in C.S.\n");
	        printMsg[0] = shareData;
	        printf("The shared data now is [%d]. (Should be 2)\n", printMsg);
	        shareData++;
		Signal(lockCV, lock);

        Release(lock);
        
        printString("t2 Complete.\n");
/*
        Acquire(cleanupLock);
        cleanupThreads--;
	Signal(cleanupCV, cleanupLock);
        Release(cleanupLock);
*/
	Exit(0);
}

void t3(){

        int printMsg[1];
/*
        Acquire(cleanupLock);
        cleanupThreads++;
        Release(cleanupLock);
*/
        
        Acquire(lock);
	
	if(flag1 == FALSE) {
		Wait(lockCV1, lock);
	}

        	printString("t3 is working in C.S.\n");
        	printMsg[0] = shareData;
        	printf("The shared data now is [%d]. (Should be 1)\n", printMsg);
        	shareData++;
		flag2 = TRUE;
		printString("t3 is now signaling\n");
		Signal(lockCV2, lock);

        Release(lock);
        
        printString("t3 Complete.\n");
/*
        Acquire(cleanupLock);
        cleanupThreads--;
	Signal(cleanupCV, cleanupLock);
        Release(cleanupLock);
*/
	Exit(0);
}

void test() {
	int id;
	int printMsg[1];

	Acquire(countLock);
	id = count;
	count++;
	Release(countLock);

	Acquire(lock);

	if(id == 3){
		Signal(lockCV, lock); /*signal the main to broadcast*/
	}

	printMsg[0] = id;
	printf("broadcast test thread [%d] is going to wait for the lock...\n", printMsg);
	Wait(lockCV, lock);

	printf("broadcast test thread [%d] has been signaled, and is ready to leave.\n", printMsg);
	Release(lock);

	Exit(0);
}




int main()
{
	int i;
        printString("-------------- Starting Test 3 --------------\n");
/*        
        cleanupLock = CreateLock();
	cleanupCV = CreateCondition();  */
        lock = CreateLock();
	lockCV = CreateCondition();
        lockCV1 = CreateCondition();
        lockCV2 = CreateCondition();

        Fork(t1);

        Fork(t2);

        Fork(t3);

	for(i = 0; i < 15; i++){
		Yield();
	}

	/*	test the broadcast system call		*/
	countLock = CreateLock();


	if(flag3 == FALSE){
		Wait(lockCV, lock);
	}
	
	printString("*** broadcast system call test ***\n");



	Acquire(lock);

	Fork(test);
	Fork(test);
	Fork(test);
	Fork(test);
	Wait(lockCV, lock);

	printString("Main call Broadcast!\n");
	Broadcast(lockCV, lock);

	

	for(i = 0; i < 15; i++){
		Yield();
	}
	Release(lock);
/*
        printString("----------------- Test 3 Eed -----------------\n");
*/        
        Exit(0);

}




